#include "logdatabase.h"

#define DB_NAME _T("//log.xdb")

CLogDataBaseImpl::CLogDataBaseImpl()
{
}
CLogDataBaseImpl::~CLogDataBaseImpl()
{
    logi("CLogDataBaseImpl::~CLogDataBaseImpl");
}
HRESULT CLogDataBaseImpl::Init(IBase* pRot, IBase* pBase)
{
    rc_error(pRot != NULL, E_FAIL);

    HRESULT hr = S_OK;
    hr = pRot->QueryInterface(IID_IRot, (void**)&m_pRot);
    rc_error(hr == S_OK, E_FAIL);

    path_string strDBPath = GetExePathString();
    strDBPath += DB_NAME;
    // logi("db_name %s", strDBPath.c_str());

    int rc = fileisexist(strDBPath.c_str());

    rc_error(rc == S_SUCCESS, S_OK);

    return S_OK;
}
HRESULT CLogDataBaseImpl::Uninit()
{
    return S_OK;
}
HRESULT CLogDataBaseImpl::Start(_pid_t pid, unsigned int type)
{
    return S_OK;
}
HRESULT CLogDataBaseImpl::Stop(unsigned int exit)
{
    return S_OK;
}
HRESULT CLogDataBaseImpl::IsTableExist(LPCSTR name, IBase** pTable)
{
    MapTableStructIterator it = m_pMapTableStruct.find(name);
    rc_error(m_pMapTableStruct.end() != it, E_FAIL);
    return it->second->QueryInterface(IID_ITableStruct, (void**)pTable);
}
HRESULT CLogDataBaseImpl::SyncTable(LPCSTR name, IBase* pBase)
{
    HRESULT hr = S_OK;

    MapTableStructIterator it = m_pMapTableStruct.find(name);
    rc_error((m_pMapTableStruct.end() == it), E_FAIL);

    ITableStruct* pITableStruct = NULL;
    hr = pBase->QueryInterface(IID_ITableStruct, (void**)&pITableStruct);
    rc_error(hr == S_OK, E_FAIL);

    m_pMapTableStruct[name] = pITableStruct;

    return S_OK;
}
HRESULT CLogDataBaseImpl::InsertTable(UCHAR* pBuf, ULONG uSize)
{
    HRESULT hr = S_OK;

    JsonSafePtr pJsonRoot = sjson_parse((char*)pBuf, 0, 0);
    rc_error(IsJsonObject(pJsonRoot.m_p), E_FAIL);

    sjsonptr pJsonTable = sjson_get_obj(pJsonRoot, Rule_Table);
    rc_error(IsJsonString(pJsonTable), E_FAIL);

    _lComPtr<ITableStruct> pTableStruct;
    pTableStruct.dispose();

    hr = this->IsTableExist(pJsonTable->valuestring, (IBase**)&pTableStruct.m_p);
    rc_error(hr == S_OK, E_FAIL);

    UINT op = pTableStruct->GetOp();

    if (TABLE_OP_UPDATE == op) {
        Update(pJsonTable->valuestring, pJsonRoot, pTableStruct);
    } else if (TABLE_OP_INSERT == op) {
        Insert(pJsonTable->valuestring, pJsonRoot, pTableStruct);
    } else if (TABLE_OP_REFRESH == op) {
        Refresh(pJsonTable->valuestring, pJsonRoot, pTableStruct);
    }

    return S_OK;
}
HRESULT CLogDataBaseImpl::OpenErrorLogDataBase()
{
    return S_OK;
}

HRESULT CLogDataBaseImpl::UpdateTable(LPCSTR name, ITableStruct* pITableStruct)
{
    return S_OK;
}
HRESULT CLogDataBaseImpl::CreateTable(LPCSTR name, ITableStruct* pITableStruct)
{
    // logi("create==>");

    HRESULT hr = S_OK;

    Table table;
    ULONG uFieldCount = 0;

    pITableStruct->GetFieldsCount(uFieldCount);
    rc_error(uFieldCount > 0, E_FAIL);

    table.resize(uFieldCount);

    hr = pITableStruct->GetTableRecords(&table[0], uFieldCount);
    rc_error(hr == S_OK, E_FAIL);

    string strSql = "CREATE TABLE IF NOT EXISTS ";
    strSql += name;
    strSql += "(";

    strSql += FILED_ID;
    strSql += " ";
    strSql += "INTEGER PRIMARY KEY NOT NULL,";

    strSql += FILED_S_TIME;
    strSql += " ";
    strSql += "INTEGER,";

    strSql += FILED_L_TIME;
    strSql += " ";
    strSql += "INTEGER,";

    UINT uloop = 0;

    for (uloop = 0; uloop < uFieldCount; uloop++) {
        FieldSturct& field = table[uloop];
        rc_error_continue((field.name != NULL && field.type != NULL));

        CharArrayPtr FieldString = new char[FILED_SQL_LEN]();

        if (s_stricmp(field.type, FIELD_TYPE_STRING) == 0) {
            s_strlcatf(FieldString, FILED_SQL_LEN - 1, "%s varchar(%u)", field.name, field.size);
        } else if (s_stricmp(field.type, FIELD_TYPE_INT) == 0) {
            s_strlcatf(FieldString, FILED_SQL_LEN - 1, "%s int", field.name);
        }

        strSql += FieldString;

        if (uloop == uFieldCount - 1) {
            strSql += " ";
        } else {
            strSql += ", ";
        }
    }

    strSql += ")";

    // logi("sql=>%s", strSql.c_str());
    ExeCommand(strSql.c_str());
    return S_OK;
}

HRESULT CLogDataBaseImpl::Insert(LPCSTR name, sjsonptr pRoot, ITableStruct* pITableStruct)
{
    return S_OK;
}

HRESULT CLogDataBaseImpl::Update(LPCSTR name, sjsonptr pRoot, ITableStruct* pITableStruct)
{
    HRESULT hr = S_OK;

    Table table;
    hr = GetTableFields(table, pITableStruct);
    rc_error(hr == S_OK, E_FAIL);

    ULONG uFieldCount = table.size();

    string strSql;

    strSql = "UPDATE ";
    strSql += name;
    strSql += " ";
    strSql += "SET ";

    UINT uloop = 0;

    for (uloop = 0; uloop < uFieldCount; uloop++) {
        sjsonptr pJsonItem = sjson_get_obj(pRoot, table[uloop].name);

        rc_error_continue(table[uloop].index == 0);

        CharArrayPtr FieldString = new char[FILED_SQL_LEN]();

        if (s_stricmp(table[uloop].type, FIELD_TYPE_STRING) == 0) {
            if (IsJsonString(pJsonItem)) {
                s_strlcatf(FieldString, FILED_SQL_LEN - 1, "%s='%s'", table[uloop].name, pJsonItem->valuestring);
                strSql += FieldString;
                strSql += ",";
            }
        } else if (s_stricmp(table[uloop].type, FIELD_TYPE_INT) == 0) {
            if (IsJsonNumber(pJsonItem)) {
                s_strlcatf(FieldString, FILED_SQL_LEN - 1, "%s=%d", table[uloop].name, pJsonItem->valueint);
                strSql += FieldString;
                strSql += ",";
            }
        }
    }

    if (strSql[strSql.length() - 1] == ',') {
        strSql.erase(strSql.end() - 1);
    }

    strSql += " WHERE ";

    for (uloop = 0; uloop < uFieldCount; uloop++) {
        sjsonptr pJsonItem = sjson_get_obj(pRoot, table[uloop].name);

        rc_error_continue(table[uloop].index == 1);

        CharArrayPtr FieldString = new char[FILED_SQL_LEN]();

        if (s_stricmp(table[uloop].type, FIELD_TYPE_STRING) == 0) {
            if (IsJsonString(pJsonItem)) {
                s_strlcatf(FieldString, FILED_SQL_LEN - 1, "%s='%s'", table[uloop].name, pJsonItem->valuestring);
                strSql += FieldString;
                strSql += " AND ";
            }
        } else if (s_stricmp(table[uloop].type, FIELD_TYPE_INT) == 0) {
            if (IsJsonNumber(pJsonItem)) {
                s_strlcatf(FieldString, FILED_SQL_LEN - 1, "%s=%d", table[uloop].name, pJsonItem->valueint);
                strSql += FieldString;
                strSql += " AND ";
            }
        }
    }

    size_t pos = strSql.find_last_of(" AND ");
    if (pos) {
        size_t len = strSql.length();
        len = len - s_strlen(" AND ");
        strSql = strSql.substr(0, len);
    }

    ExeCommand(strSql.c_str());

    return S_OK;
}

HRESULT CLogDataBaseImpl::Refresh(LPCSTR name, sjsonptr pRoot, ITableStruct* pITableStruct)
{
    HRESULT hr = S_OK;
    Table table;
    hr = GetTableFields(table, pITableStruct);
    rc_error(hr == S_OK, E_FAIL);

    string strSql;

    strSql = "DELETE FROM";
    strSql += " ";
    strSql += name;

    return Insert(name, pRoot, pITableStruct);
}

HRESULT CLogDataBaseImpl::GetTableFields(Table& table, ITableStruct* pITableStruct)
{
    HRESULT hr = S_OK;

    ULONG uFieldCount = 0;

    pITableStruct->GetFieldsCount(uFieldCount);
    rc_error(uFieldCount > 0, E_FAIL);

    table.resize(uFieldCount);

    hr = pITableStruct->GetTableRecords(&table[0], uFieldCount);
    rc_error(hr == S_OK, E_FAIL);

    return S_OK;
}

HRESULT CLogDataBaseImpl::ExeCommand(LPCSTR cmd)
{
    return S_OK;
}
